/**
 * 获取数据类型
 *
 * getType([]) -> "[object Array]"
 *
 * @param target
 * @returns {string}
 */
export function toRawType (target) {
  return Object.prototype.toString.call(target)
}

/**
 * 获取对象的数据类型
 *
 * getType([]) -> "array"
 *
 * @param target 目标对象
 * @returns {string}
 */
export function getType (target) {
  return toRawType(target).slice(8, -1).toLowerCase()
}

/**
 * 获取对象的数据类型
 *
 * getType([], "array") -> true
 *
 * @param target 目标对象
 * @param { string } type 目标类型
 * @returns { boolean }
 */
export function isType (target, type) {
  return getType(target) === type
}

const create = options => {
  if (func instanceof Worker) return func;
  if (typeof func === 'string' && func.endsWith('.js')) return new Worker(func);

  if (isType(options)) {
    const code = [
      `self.injectFn = ${ func.toString() };\n`,
      'self.onmessage = (e) => {\n',
      ' const result = self.injectFn(e.data);\n',
      ' self.postMessage(result);\n',
      '}'
    ];


    for (const [name, func] of Object.entries(options)) {
      code.push(
        `self.${name} = ${func.toString()}`
      )
    }

    code.push(`self.onmessage = (e) => {\n`)
    code.push(`  const { type, ...data } = e.data;\n`)
    code.push(`  const result = self.${type}(e.data);\n`)
    code.push(`  self.postMessage(result);\n`)
    code.push(`}`)
  }



  if (typeof func === 'object') {
    const code = [
      `self.injectFn = ${ func.toString() };\n`,
      'self.onmessage = (e) => {\n',
      ' const result = self.injectFn(e.data);\n',
      ' self.postMessage(result);\n',
      '}'
    ];



    const blob = new Blob(code, { type: 'text/javascript' });
    const url = URL.createObjectURL(blob);
    const worker = new Worker(url);

    worker.cleanup = () => {
      URL.revokeObjectURL(url);
      worker.terminate();
    };

    return worker
  } else {
    console.error('参数必须是一个函数')
  }
};

const useWorker = (options, i) => {
  const worker = create(options);

  if (!worker) {
    throw new Error('Need correctly parameter!');
  }

  worker.postMessage(i);

  return new Promise((resolve, reject) => {
    worker.onmessage = e => {
      if (worker.cleanup) worker.cleanup();
      resolve(e.data);
    };

    worker.onerror = e => {
      if (worker.cleanup) worker.cleanup();
      reject(e.message);
    };

    worker.onmessageerror = (e) => {
      if (worker.cleanup) worker.cleanup();
      reject(e.message);
    };
  });
};

